package org.bilinc.gz001.dao.recover;


import org.apache.commons.lang.StringUtils;
import org.bilinc.gz001.Utils;
import org.bilinc.gz001.dao.ResourceDao;
import org.bilinc.gz001.dao.interfaces.AbstractDaoImpl;
import org.bilinc.gz001.dao.interfaces.IMonthDao;
import org.bilinc.gz001.entity.Month;
import org.bilinc.gz001.entity.Resource;
import org.hibernate.NonUniqueResultException;
import org.hibernate.Session;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Calendar;
import java.util.List;

@Component
public class RecoverCalendar extends AbstractDaoImpl<Month> implements IMonthDao {

    @Autowired
    ResourceDao resourceDao;

    private final static String HQL_GET_MONTH = "SELECT r FROM Month r where r.yearNumber = :yearN AND r.monthNumber = :monthN AND r.resource.tabNumber=:tabelNomer";

    RecoverCalendar() {
    }

    public void emergencyRecoverCalendarFromCorrupted(int year, Integer month, int day, String tabNumber) {
        Resource resource = resourceDao.findByTanelNumber(tabNumber);
        System.out.println("***********************************");
        System.out.println("******Calendar is corrupted********");
        System.out.println("*********Emergency help!***********");
        System.out.println("***********************************");

        if (month == null) {
            createMissedMonthsForResourceEmergencyUse(year, resource);
            return;
        } else {
            System.out.println("Ошибка обнаружена в " + month+1 + " месяце у товарища " + resource.getFullName());
            System.out.println("Восстанавливаемся...");
        }

        Session session  = getSessionStartTransaction();

        Month monthWorkerData = (Month) session.createQuery(HQL_GET_MONTH)
                .setInteger("yearN", year)
                .setInteger("monthN", month)
                .setString("tabelNomer", tabNumber)
                .uniqueResult();

        String data = "";
        StringBuilder sb = new StringBuilder();
        String pattern = ";";

        if (monthWorkerData != null) {
            data = monthWorkerData.getData();
        } else {
            if (month != null) {
                System.out.println("Восстановление невозможно, создаем новый месяц вместо старого");
                recreateMonthForResourceEmergencyUse(year, month, resource);
                return;
            } else {
                System.out.println("Восстановление невозможно, пройдемся по всем месяцам и создадим недостающие");
                createMissedMonthsForResourceEmergencyUse(year, resource);
                return;
            }
        }


        StringBuilder ficesMonth = new StringBuilder();
        List<String> corruptedDaysOfMonth = Utils.split(data, pattern);
            for (int countDay = 0; countDay < Utils.DAYS_PER_MONTH[month]; countDay++) {
                try{
                    sb.append(corruptedDaysOfMonth.get(countDay) + pattern);
                } catch (IndexOutOfBoundsException e) {
                    sb.append(pattern);
                }
            }

        monthWorkerData.setData(sb.toString());
        session.saveOrUpdate(monthWorkerData);
        System.out.println("Записываем в БД...");
        commitTransaction();
    }

    public Month recreateMonthForResourceEmergencyUse(int year, int month, Resource resource) {
        Session session = getSession();
        StringBuilder sb = new StringBuilder();
            sb.setLength(0);
            for (int dayCount = 1; dayCount <= Utils.DAYS_PER_MONTH[month]; dayCount++) {
                sb.append(";");
            }
            Month monthWorkerData = new Month();
            monthWorkerData.setYearNumber(2013);
            monthWorkerData.setMonthNumber(month);
            monthWorkerData.setResource(resource);
            monthWorkerData.setData(sb.toString());
        session.saveOrUpdate(monthWorkerData);
        commitTransaction();
        //TODO проверить каскад
        return monthWorkerData;
    }

    public void createMissedMonthsForResourceEmergencyUse(int year, Resource resource) {
        System.out.println("восстанавливаем потерянные месяцы...");
        Session session = getSessionStartTransaction();
        for (int i = 0; i < 12; i++) {
            Month monthWorkerData = null;
            try {
                monthWorkerData = (Month) session.createQuery(HQL_GET_MONTH)
                        .setInteger("yearN", year)
                        .setInteger("monthN", i)
                        .setString("tabelNomer", resource.getTabNumber())
                        .uniqueResult();
            } catch (NonUniqueResultException e) {
                System.out.println("Стираем лишние...");
                List<Month> monthsForDelete = session.createQuery(HQL_GET_MONTH)
                        .setInteger("yearN", year)
                        .setInteger("monthN", i)
                        .setString("tabelNomer", resource.getTabNumber())
                        .list();
                for (int missedMonthCounter = 1; missedMonthCounter<monthsForDelete.size(); missedMonthCounter++) {  //начали не с нуля тк оставляем один месяц
                    session.delete(monthsForDelete.get(i));
                }
                commitTransaction();
                return;
            }

            if (monthWorkerData != null) {
                continue;
            }
            StringBuilder sb = new StringBuilder();
            sb.setLength(0);
            for (int dayCount = 1; dayCount <= Utils.DAYS_PER_MONTH[i]; dayCount++) {
                sb.append(";");
            }
            monthWorkerData = new Month();
            monthWorkerData.setYearNumber(2013);
            monthWorkerData.setMonthNumber(i);
            monthWorkerData.setResource(resource);
            monthWorkerData.setData(sb.toString());
            getSession().save(monthWorkerData);
            //TODO проверить каскад
        }
        commitTransaction();
        System.out.println("Создали нехватающие месяцы!");
    }



}
